/**
* @File    :   jwt.go
* @Time    :   2022/05/05
* @Author  :   Mz100
* @Desc    :   None
 */
package jwt

import (
	"errors"
	"fmt"
	"time"
	"xdkaika/libs/redis"
	"xdkaika/models"

	"github.com/beego/beego/v2/core/logs"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/golang-jwt/jwt"
)

var jwtSecret []byte
var bearerLength = len("Bearer ")

type UserClaims struct {
	models.UserProfile
	jwt.StandardClaims
}

func init() {
	jwtSecret = []byte(beego.AppConfig.DefaultString("jwtsecret", "xdkaika"))
}

// 生成token
func GenerateToken(u *models.User) (string, error) {

	expireTime := time.Hour * 24 * 100
	stdClaims := jwt.StandardClaims{
		ExpiresAt: (time.Now().Add(expireTime)).Unix(),
		Issuer:    "xdkaika",
	}
	userProfile := models.GetUserProfile(u)
	userClaims := &UserClaims{
		StandardClaims: stdClaims,
		UserProfile:    *userProfile,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, userClaims)
	tokenString, err := token.SignedString(jwtSecret)
	if err != nil {
		logs.Error(err)
	}
	//redis 存储jwt token
	redis := redis.GetRedis()
	var key = beego.AppConfig.DefaultString("redistokenkey", "jwttoken_") + userProfile.OpenId
	redis.Set(key, tokenString, time.Duration(expireTime))
	// end redis
	return tokenString, err
}

// 验证token
func ValidateToken(tokenString string) (*models.UserProfile, error) {
	if tokenString == "" {
		return nil, errors.New("令牌不存在")
	}
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})
	if token == nil {
		return nil, errors.New("令牌无效")
	}
	claims := UserClaims{}
	_, err = jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		return jwtSecret, nil
	})
	if err != nil {
		logs.Error(err)
		return nil, err
	}
	fmt.Println("tokenString", tokenString)
	// redis 验证
	redis := redis.GetRedis()
	var key = beego.AppConfig.DefaultString("redistokenkey", "jwttoken_") + claims.UserProfile.OpenId
	redisToken := redis.Get(key)
	fmt.Println("redis token", redisToken)
	if redisToken != nil && redisToken == tokenString {
		return &claims.UserProfile, err
	}
	return nil, err

}

// 删除 token
func DeleteToken(u *models.UserProfile) (bool, error) {
	if u.OpenId != "" {
		redis := redis.GetRedis()
		var key = beego.AppConfig.DefaultString("redistokenkey", "jwttoken_") + u.OpenId
		err := redis.Delete(key)
		if err == nil {
			return true, nil
		} else {
			return false, err
		}
	}
	return false, errors.New("OpenId 为空")
}
